<?php
namespace TwinPeaks\Core\Datatype;

const EMAIL_TYPE = 'email';

class CEmail extends CString
{
	/**
	 * @return void
	 */
	function __construct($value = null)
	{
		parent::__construct($value);
		$this->type = EMAIL_TYPE;
	}
	
	/**
	 * Source: http://www.linuxjournal.com/article/9585
	 * 
	 * @return boolean
	 */
	final function isValid()
	{
		$isValid = true;
		$atIndex = strrpos($this->value, "@");
		if (is_bool($atIndex) && !$atIndex)
			$isValid = false;
		else
		{
			$domain = substr($this->value, $atIndex + 1);
			$local = substr($this->value, 0, $atIndex);
			$localLen = strlen($local);
			$domainLen = strlen($domain);
			if ($localLen < 1 || $localLen > 64)
				// local part length exceeded
				$isValid = false;
			else if ($domainLen < 1 || $domainLen > 255)
				$isValid = false;
			else if ($local[0] == '.' || $local[$localLen-1] == '.')
				// local part starts or ends with '.'
				$isValid = false;
			else if (preg_match('/\\.\\./', $local))
				// local part has two consecutive dots
				$isValid = false;
			else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain))
				// character not valid in domain part
				$isValid = false;
			else if (preg_match('/\\.\\./', $domain))
				// domain part has two consecutive dots
				$isValid = false;
			else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/',
				str_replace("\\\\","",$local)))
			{
				// character not valid in local part unless 
				// local part is quoted
				if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local)))
					$isValid = false;
			}
		
			if ($isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A")))
				// domain not found in DNS
				$isValid = false;
		}

		return $isValid;
	}
}
